/*
 * @Author: Lin Hongwei
 * @Date: 2022-10-07 15:27:17
 * @LastEditTime: 2022-11-05 10:09:48
 * @LastEditors: Lin Hongwei
 * @email: 1365755396@qq.com
 * @CSDN: https://blog.csdn.net/weixin_45429409
 * @Description: react-query实现乐观更新的主要配置
 */

import { QueryKey, useQueryClient } from "react-query";
import { SortParam } from "../types/sort-param";

/**
 * @description: useMutate乐观更新配置
 * @param {QueryKey} queryKey - useQuery的key
 * @param {function} callback - 数据操作的具体函数
 *  target - 当前更新的数据
 *  old - 更新之前缓存中的数据
 * @return {*} 返回配置项
 */
export const useOptimisticConfigBuilder = (
  queryKey: QueryKey,
  callback: (target: any, old?: any[]) => any[]
) => {
  const queryClient = useQueryClient();
  return {
    onSuccess: (data: any, variables: any, context: any) =>
      queryClient.invalidateQueries(queryKey), //让缓冲更新（会重新调用projects键的请求函数）
    onMutate: (variables: any) => {
      //调用mutate方法的回调函数
      const oldData = queryClient.getQueryData(queryKey); //获取一个快照
      queryClient.setQueryData(queryKey, (old?: any[]) =>
        callback(variables, old)
      ); //先同步本地更新
      return { oldData }; //将快照返回
    },
    onError: (error: any, variables: any, context: any) =>
      queryClient.setQueryData(queryKey, context?.oldData), //错误的时候将更新的数据进行回滚
  };
};

/**
 * @description: 针对增加的乐观更新
 * @param {QueryKey} queryKey
 * @return {*}
 */
export const useOptimisticAddConfig = (queryKey: QueryKey) =>
  useOptimisticConfigBuilder(queryKey, (target, oldData) => [
    ...(oldData || []),
    target,
  ]);

/**
 * @description: 针对删除的乐观更新
 * @param {QueryKey} queryKey
 * @return {*}
 */
export const useOptimisticDeleteConfig = (queryKey: QueryKey) =>
  useOptimisticConfigBuilder(
    queryKey,
    (target, oldData) => oldData?.filter((item) => item.id != target.id) || []
  );

/**
 * @description: 针对更新的乐观更新
 * @param {QueryKey} queryKey
 * @return {*}
 */
export const useOptimisticUpdateConfig = (queryKey: QueryKey) =>
  useOptimisticConfigBuilder(
    queryKey,
    (target, oldData) =>
      oldData?.map((item) =>
        item.id == target.id ? { ...item, ...target } : item
      ) || []
  );

/**
 * @description: 针对排序的乐观更新
 * @param {QueryKey} queryKey
 * @return {*}
 */
export const useOptimisticSortConfig = (queryKey: QueryKey) =>
  useOptimisticConfigBuilder(queryKey, renderFun);

/**
 * @description: 排序函数
 * @return {*}
 */
export const renderFun = (target: SortParam, oldData?: any[]) => {
  console.log("移动后----", target);
  let { sortType, fromIndex, toIndex, kanbanId } = target;
  let newData = Array.from(oldData || []);
  let [remove] = newData.splice(fromIndex, 1); //移动的元素
  if (!sortType) {
    //看板移动，或则任务只是在当前看板移动
    newData.splice(toIndex, 0, remove); //插入到指定位置
  }
  if (!!sortType) {
    //跨看板移动
    //当to的下一个刚好是from
    //当toIndex为总数组的最后一个
    // remove.kanbanId = fromIndex==toIndex || toIndex+1>(oldData?.length||0) ? kanbanId : oldData?.[toIndex].kanbanId;
    remove.kanbanId = kanbanId;
    if (fromIndex < toIndex) toIndex -= 1;
    newData.splice(toIndex, 0, remove);
  }

  return newData;
};
